using System;
using System.Diagnostics;

namespace GraphSpace
{
	class MainClass
	{
		public static int Main (string[] args)
		{
			Stopwatch time = new Stopwatch ();
			// $file
			// -s $ - startknoten
			// -t $- zielknoten
			// -z - zielgerichtet
			// -b - bi
			// -h - binheap
			// -d - dail
			
			//string dateipfad = "graph.txt";
			//args[0];
			string dateipfad = args[0];
			
			int minOp = 0;
			double distance = 0;
			int startknoten = System.Convert.ToInt32 (args[2]);
			int zielknoten = System.Convert.ToInt32 (args[4]);
			Knoten[] Pfad;
			
			//Console.Write("Graph einlesen ...");
			Graph G = new Graph ();
			G.ladeEuklidGraph (dateipfad);
			//Console.WriteLine(" done");
			
			//Console.WriteLine("n = "+G.V.Count+" m = "+G.M + " c = "+ G.bestimmeMaxKantengewicht());
			
			bool bidirect = false, dial = false, goal = false;
			
			#region die Optionen einlesen und entsprechende Flags setzen
			for (int i = 5; i < args.Length; i++)
			{
				switch (args[i])
				{
				case "-z":
					
					{
						goal = true;
						break;
					}

				case "-b":
					
					{
						bidirect = true;
						break;
					}

				case "-h":
					
					{
						//binheap = true;
						break;
					}

				case "-d":
					
					{
						dial = true;
						break;
					}

				default:
					
					{
						Console.WriteLine ("Falscher Parameter!");
						break;
					}

				}
			}
			#endregion
			
			if (dial && goal)
			{
				Console.WriteLine ("-z und -d lassen sich nicht trivial kombinieren, daher wurden Heaps gewählt");
				dial = false;
			}
			
			// Bidirektionale Suche
			if (bidirect)
			{
				// Kopie des Graphen erstellen
				//Console.Write("Kopie des Graphen erstellen ... ");
				Graph G2 = new Graph ();
				G2.ladeEuklidGraph (dateipfad);
				//Console.WriteLine(" done");
				// zweimal Dials Implemtierung (Bidirektional)
				if (dial)
				{
					// TODO
					time.Start ();
					BiSearch<Dial, Dial> Search = new BiSearch<Dial, Dial> (G.bestimmeMaxKantengewicht ());
					distance = Search.DoSearch (G, G2, startknoten, zielknoten, out Pfad, goal, goal);
					time.Stop ();
					minOp = Search.getDeleteMin ();
				}

				// zwei einfache Binärheaps (Bidirektional)
				else
				{
					// TODO
					time.Start ();
					BiSearch<BinaryHeap, BinaryHeap> Search = new BiSearch<BinaryHeap, BinaryHeap> ();
					distance = Search.DoSearch (G, G2, startknoten, zielknoten, out Pfad, goal, goal);
					time.Stop ();
					minOp = Search.getDeleteMin ();
				}
			}

			// Suche in einer Richtung
			else
			{
				// Dials Implemtierung (n. Bidirektional)
				if (dial)
				{
					// TODO
					time.Start ();
					uniSearch<Dial> Search = new uniSearch<Dial> (G.bestimmeMaxKantengewicht ());
					distance = Search.DoSearch (G, G.V[startknoten], G.V[zielknoten], out Pfad, goal);
					time.Stop ();
					minOp = Search.getDeleteMin ();
				}

				// einfacher Binärheap (n. Bidirektional)
				else
				{
					// TODO
					time.Start ();
					uniSearch<BinaryHeap> Search = new uniSearch<BinaryHeap> ();
					distance = Search.DoSearch (G, G.V[startknoten], G.V[zielknoten], out Pfad, goal);
					time.Stop ();
					minOp = Search.getDeleteMin ();
				}
			}
			
			Console.WriteLine (distance);
			
			Console.WriteLine (time.ElapsedMilliseconds);
			
			Console.WriteLine (minOp);
			
			return 0;
		}
	}
}
